package net.j4love.nio.quickstart;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;

/**
 * @author He Peng
 * @create 2017-07-28 23:47
 * @update 2017-07-28 23:47
 * @updatedesc : 更新说明
 * @see
 */
public class NIOEchoServer implements EchoServer {

    private static final boolean BLOCKING = true;
    private static final boolean NON_BLOCKING = false;
    private ServerSocketChannel serverSocketChannel;
    private Selector selector;

    public static void main(String[] args) throws IOException {
        NIOEchoServer nioEchoServer = new NIOEchoServer();
        nioEchoServer.bind("192.168.1.137",8080);
        nioEchoServer.accept();
    }

    @Override
    public String echo(String source) {
        if (null == source) {
            source = "null";
        }
        return source;
    }

    public void bind(String host,int port) throws IOException {
        this.serverSocketChannel = ServerSocketChannel.open();
        this.serverSocketChannel.configureBlocking(NON_BLOCKING);
        this.serverSocketChannel.bind(new InetSocketAddress(host,port) , 1024);
        this.selector = Selector.open();
        this.serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("NIOEchoServer started , host [" + host + "] , port [" + port + "]");
    }

    public void accept() throws IOException {
        while (null != this.serverSocketChannel
                && null != this.selector
                && this.selector.isOpen()) {
            int select = this.selector.select(500);
            if (select == 0) {
                continue;
            }

            Iterator<SelectionKey> iterator = this.selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                iterator.remove();
                if (selectionKey.isConnectable()) {
                    System.out.println("The connection is ready");
                } else if (selectionKey.isAcceptable()) {
                    System.out.println("NIOEchoServer accept a Connection");
                    ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(NON_BLOCKING);
                    socketChannel.register(this.selector,SelectionKey.OP_READ);
                } else if (selectionKey.isReadable()) {
                    System.out.println("SocketChannel Read is ready");
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    ByteBuffer bBuf = ByteBuffer.allocateDirect(1024 * 2);
                    socketChannel.read(bBuf);
                    bBuf.flip();
                    byte[] dst = new byte[bBuf.limit()];
                    bBuf.get(dst,0,dst.length);
                    String body = new String(dst,"utf-8");
                    System.out.println("Received client data : " + body);

                    // write to client
                    String formatTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()).toString();
                    String echo = echo(body) + " " + formatTime;
                    ByteBuffer src = ByteBuffer.allocateDirect(1024);
                    src.put(echo.getBytes("UTF-8"));
                    src.flip();
                    socketChannel.write(src);
                    socketChannel.close();
                } else if (selectionKey.isWritable()) {

                }
            }
        }
    }
}
